/**
 * 通用请求队列系统 - 完整实现
 * 完全兼容原有 request 和 requestByUrl 方法
 */

import layerFun from '@/common/comFun/layerFun.js';
var layer = layerFun;

class UniversalRequestQueue {
	constructor(APP, utils) {
		this.queue = [];
		this.activeRequest = null;
		this.requestMap = new Map();
		this.eventListeners = new Map();

		this.APP = APP;
		this.utils = utils;
		this.defaultConfig = {
			queueId: 'default',
			priority: 0,
			skipQueue: false,
			retry: 4,
			timeout: 10000,
			ignoreError: false,
			loading: true,
			toastError: true,
			original: false,
			IP: null,
			dataType: null,
			cmd: null,
			method: 'POST',
			header: {
				'content-type': 'application/x-www-form-urlencoded;charset=utf-8',
				// 'username': this.APP.getUserInfo().UserName
			}
		};

	}
	// 添加新的事件类型常量
	static get EVENTS() {
		return {
			QUEUE_EMPTY: 'queueEmpty',
			REQUEST_START: 'requestStart', // 触发时传递任务ID和任务对象。
			REQUEST_SUCCESS: 'requestSuccess', // 传递任务ID和结果。
			REQUEST_FAIL: 'requestFail', // 传递任务ID和错误对象。
			REQUEST_CANCEL: 'requestCancel', // 传递任务ID。
			REQUEST_RETRY: 'requestRetry', // 传递任务ID、当前重试次数、剩余重试次数。
			QUEUE_CHANGE: 'queueChange', // 传递当前队列（可以是一个数组的副本，避免外部修改）和当前活动任务。
			UPLOAD_PROGRESS: 'uploadProgress' // 新增上传进度事件
		};
	}

	request(url, data, success, fail, config = {}) {
		const mergedConfig = {
			...this.defaultConfig,
			...config
		};
		const requestId = `req_${Date.now()}_${Math.random().toString(36).slice(2, 6)}`;
		const requestTask = {
			id: requestId,
			url,
			data,
			success,
			fail,
			// fail: (err) => {
			// 	// layer.alert(JSON.stringify(err))
			// 	return fail
			// },
			config: mergedConfig,
			status: 'pending',
			createdAt: Date.now(),
			task: null
		};

		this.requestMap.set(requestId, requestTask);
		if (mergedConfig.skipQueue) {
			this._executeRequest(requestTask);
			return () => this.cancel(requestId);
		}
		this._enqueue(requestTask);
		this._processQueue();

		return () => this.cancel(requestId);
	}

	originalRequest(cmd, param, successCallback, errorCallback, IP, data) {
		let header = {
			'content-type': 'application/x-www-form-urlencoded;charset=utf-8',
		}
		if (!this.utils.isEmpty(this.APP.getUserInfo())) {

			let username = this.APP.getUserInfo().UserName || '';
			header['username'] = encodeURIComponent(username)
		}
		return this.request(
			cmd,
			param,
			successCallback,
			errorCallback, {
				original: true,
				IP,
				dataType: data,
				cmd,
				method: 'POST',
				header: header
			}
		);
	}

	requestByUrl(requestUrl, param, successCallback, errorCallback, IP, data) {
		let header = {
			'content-type': 'application/x-www-form-urlencoded;charset=utf-8',
		}
		if (!this.utils.isEmpty(this.APP.getUserInfo())) {
			let username = this.APP.getUserInfo().UserName || '';
			header['username'] = encodeURIComponent(username)
		}
		return this.request(
			requestUrl,
			param,
			successCallback,
			errorCallback, {
				original: true,
				IP,
				dataType: data,
				requestUrl,
				method: 'POST',
				header: header
			}
		);
	}
	requestByUrlSub(requestUrl, param, successCallback, errorCallback, IP, data) {
		let header = {
			'content-type': 'application/x-www-form-urlencoded;charset=utf-8',
		}
		if (!this.utils.isEmpty(this.APP.getUserInfo())) {
			let username = this.APP.getUserInfo().UserName || '';
			header['username'] = encodeURIComponent(username)
		}
		return this.request(
			requestUrl,
			param,
			successCallback,
			errorCallback, {
				original: true,
				IP,
				dataType: data,
				requestUrl,
				method: 'POST',
				header: header
			}
		);
	}
	promiseRequest(cmd, param, IP, data) {
		const requestId = `req_${Date.now()}_${Math.random().toString(36).slice(2, 6)}`;
		let header = {
			'content-type': 'application/x-www-form-urlencoded;charset=utf-8',
		};
		if (!this.utils.isEmpty(this.APP.getUserInfo())) {
			let username = this.APP.getUserInfo().UserName || '';
			header['username'] = encodeURIComponent(username);
		}

		let url = '';
		if (IP) {
			if (data === 1) {
				url = IP + '?cmdname=' + cmd;
			} else if (data === 2) {
				url = IP + '?cmd=' + cmd;
			} else {
				url = IP;
			}
		} else {
			url = this.APP.IPAgreement() + this.APP.serverIP() + '/Frame/SqlData?cmdname=' + cmd;
		}

		const paramWithUser = {
			...param
		};
		if (this.APP.getUserInfo()) {
			const userInfo = this.APP.getUserInfo();
			['P_UserID', 'P_UserName', 'P_UserCode', 'P_EmplID'].forEach(key => {
				if (!paramWithUser.hasOwnProperty(key)) {
					paramWithUser[key] = userInfo[key.replace('P_', '')];
				}
			});
		}
		console.log(url);
		console.log(paramWithUser);

		let requestTask;
		const promise = new Promise((resolve, reject) => {
			requestTask = uni.request({
				url: url,
				data: paramWithUser,
				method: 'POST',
				header: header,
				success: (ret) => {
					if (ret?.data) {
						if (ret.data.status === 200) {
							resolve(ret.data);
						} else {
							reject(ret.data);
						}
					} else {
						reject(new Error('Empty response'));
					}
				},
				fail: (err) => {
					reject(err);
				}
			});
		});

		// 添加 abort 方法便于外部取消
		promise.abort = () => {
			if (requestTask && typeof requestTask.abort === 'function') {
				requestTask.abort();
			}
		};

		return promise;
	}
	promiseRequestByUrl(requestUrl, param, IP, data) {
		const requestId = `req_${Date.now()}_${Math.random().toString(36).slice(2, 6)}`;
		let cancelFn;
		let header = {
			'content-type': 'application/x-www-form-urlencoded;charset=utf-8',
		}
		if (!this.utils.isEmpty(this.APP.getUserInfo())) {
			let username = this.APP.getUserInfo().UserName || '';
			header['username'] = encodeURIComponent(username)
		}
		const promise = new Promise((resolve, reject) => {
			cancelFn = this.request(
				requestUrl,
				param,
				(res) => resolve(res),
				(err) => reject(err), {
					original: true,
					IP,
					dataType: data,
					requestUrl,
					method: 'POST',
					header: header,
					skipQueue: true
				}
			);
		});

		promise.abort = cancelFn;
		return promise;
	}

	upload(url, filePath, formData, success, fail, config = {}) {
		const progressCallback = config.onProgress;
		delete config.onProgress;
		return this.request(
			url, {
				filePath,
				formData
			},
			success,
			fail, {
				method: 'UPLOAD',
				...config,
				onProgress: progressCallback // 保留进度回调
			}
		);
	}

	cancel(requestId) {
		const requestTask = this.requestMap.get(requestId);
		if (!requestTask) return;

		this.queue = this.queue.filter(req => req.id !== requestId);
		if (requestTask.status === 'running' && requestTask.task) {
			requestTask.task.abort();
			this._emit(UniversalRequestQueue.EVENTS.REQUEST_CANCEL, {
				requestId,
				task: requestTask
			});
		}

		if (typeof requestTask.fail === 'function') {
			requestTask.fail(new Error('Request cancelled'));
		}

		this.requestMap.delete(requestId);
		this._emit(UniversalRequestQueue.EVENTS.QUEUE_CHANGE, this._getQueueStatus());
		this._processQueue();
	}

	clear(queueId = 'default') {
		this.queue = this.queue.filter(task => {
			if (task.config.queueId === queueId) {
				this.requestMap.delete(task.id);
				return false;
			}
			return true;
		});
	}


	on(event, callback) {
		if (!this.eventListeners.has(event)) {
			this.eventListeners.set(event, []);
		}
		this.eventListeners.get(event).push(callback);
	}

	off(event, callback) {
		if (!this.eventListeners.has(event)) return;

		if (!callback) {
			this.eventListeners.delete(event);
			return;
		}

		const callbacks = this.eventListeners.get(event);
		const index = callbacks.indexOf(callback);
		if (index !== -1) callbacks.splice(index, 1);
		if (callbacks.length === 0) this.eventListeners.delete(event);
	}

	_emit(event, ...args) {
		if (this.eventListeners.has(event)) {
			this.eventListeners.get(event).forEach(callback => callback(...args));
		}
	}

	async _executeRequest(task) {
		if (task.status !== 'pending') return;

		this.activeRequest = task;
		task.status = 'running';
		// 触发请求开始事件
		this._emit(UniversalRequestQueue.EVENTS.REQUEST_START, {
			requestId: task.id,
			task
		});
		this._emit(UniversalRequestQueue.EVENTS.QUEUE_CHANGE, this._getQueueStatus());

		let retryCount = task.config.retry;
		let retryIndex = 0;
		let lastError = null;

		while (retryCount >= 0) {
			try {
				const result = await this._executeApiCall(task);
				this._handleSuccess(task, result);
				return;
			} catch (error) {
				lastError = error;

				// 触发重试事件
				if (retryCount > 0) {
					this._emit(UniversalRequestQueue.EVENTS.REQUEST_RETRY, {
						requestId: task.id,
						retryIndex: retryIndex + 1,
						totalRetries: task.config.retry,
						error
					});
				}

				retryCount--;
				retryIndex++;
				if (retryCount >= 0) await this._delay(1000);
			}
		}

		this._handleError(task, lastError);
	}

	async _executeApiCall(task) {
		if (task.config.original) {
			return task.config.requestUrl ?
				this._executeOriginalRequestByUrl(task) :
				this._executeOriginalRequest(task);
		}

		if (task.config.method === 'UPLOAD') {
			return this._executeUpload(task);
		}

		return this._executeNormalRequest(task);
	}

	_executeOriginalRequest(task) {
		return new Promise((resolve, reject) => {
			// uni.onNetworkStatusChange((res) => {
			// 	if (!res.isConnected) {
			// 		uni.showToast({
			// 			title: '网络连接不可用！',
			// 			icon: 'none'
			// 		});
			// 	}
			// });
			uni.getNetworkType({
				success: (res) => {
					if (res.networkType === 'none') {
						uni.showToast({
							title: '网络连接不可用！',
							icon: 'none'
						});
						return reject(new Error('网络连接不可用'));
					}
				},
				fail: () => {
					uni.showToast({
						title: '无法获取网络状态',
						icon: 'none'
					});
					return reject(new Error('无法获取网络状态'));
				}
			});


			let url = '';
			const {
				IP,
				dataType,
				cmd
			} = task.config;

			if (IP) {
				if (dataType == 1) url = IP + '?cmdname=' + cmd;
				else if (dataType == 2) url = IP + '?cmd=' + cmd;
				else url = IP;
			} else {
				url = this.APP.IPAgreement() + this.APP.serverIP() + '/Frame/SqlData?cmdname=' + cmd;
			}

			const param = {
				...task.data
			};
			if (this.APP.getUserInfo()) {
				const userInfo = this.APP.getUserInfo();
				['P_UserID', 'P_UserName', 'P_UserCode', 'P_EmplID'].forEach(key => {
					if (!param.hasOwnProperty(key)) {
						param[key] = userInfo[key.replace('P_', '')];
					}
				});
			};

			task.task = uni.request({
				url: url,
				data: param,
				method: 'POST',
				timeout: task.config.timeout,
				header: task.config.header,
				success: (ret) => {
					if (ret?.data) {
						if (ret.data.status == 200) {
							resolve(ret.data);
						} else {
							this.utils.hideLoading();
							const IPData = this.APP.serverIP();
							if (process.env.NODE_ENV === 'development') {
								uni.showToast({
									title: `${cmd}\n${IPData}\n错误代码:\n${JSON.stringify(ret)}`,
									icon: 'none'
								});
							}
							reject(ret.data);
						}
					} else {
						reject(new Error('Empty response'));
					}
				},
				fail: (err) => {
					this.utils.hideLoading();
					reject(err);
				}
			});
		});
	}


	/**
	 * 执行原始requestByUrl请求
	 */
	_executeOriginalRequestByUrl(task) {
		return new Promise((resolve, reject) => {
			// 网络状态检测
			// uni.onNetworkStatusChange((res) => {
			// 	if (!res.isConnected) {
			// 		uni.showToast({
			// 			title: '网络连接不可用！',
			// 			icon: 'none'
			// 		});
			// 	}
			// });
			// ✅ 使用 getNetworkType 一次性检测
			uni.getNetworkType({
				success: (res) => {
					if (res.networkType === 'none') {
						uni.showToast({
							title: '网络连接不可用！',
							icon: 'none'
						});
						return reject(new Error('网络连接不可用'));
					}
				},
				fail: () => {
					uni.showToast({
						title: '无法获取网络状态',
						icon: 'none'
					});
					return reject(new Error('无法获取网络状态'));
				}
			});

			// URL处理
			let url = '';
			const {
				IP,
				dataType,
				requestUrl
			} = task.config;

			if (IP) {
				if (dataType == 1) {
					url = IP + '?cmdname=' + requestUrl;
				} else if (dataType == 2) {
					url = IP + '?cmd=' + requestUrl;
				} else {
					url = IP;
				}
			} else {
				url = this.APP.IPAgreement() + this.APP.serverIP() + requestUrl;
			}

			// 用户信息注入
			const param = {
				...task.data
			};
			if (this.APP.getUserInfo()) {
				const userInfo = this.APP.getUserInfo();
				['P_UserID', 'P_UserName', 'P_UserCode', 'P_EmplID'].forEach(key => {
					if (!param.hasOwnProperty(key)) {
						param[key] = userInfo[key.replace('P_', '')];
					}
				});
			};
			if (url.indexOf("/FormList/SaveData_uniapp") != -1) {

				console.log(url);
				console.log(param);
				console.log(task.config);
			}

			// 发起请求
			task.task = uni.request({
				url: url,
				data: param,
				method: 'POST',
				timeout: task.config.timeout,
				header: task.config.header,
				success: (ret) => {

					if (ret && ret.data) {
						if (ret.data.status == 200) {
							resolve(ret.data.data);
						} else {
							this.utils.hideLoading();

							let IPData = IP || this.APP.serverIP();

							if (process.env.NODE_ENV === 'development') {
								uni.showToast({
									title: `${requestUrl}\n${IPData}\n错误代码:\n${JSON.stringify(ret)}`,
									icon: 'none'
								});
							}

							reject(ret.data);
						}
					} else {
						reject(new Error('Empty response'));
					}
				},
				fail: (err) => {
					this.utils.hideLoading();
					reject(err);
				}
			});
		});
	}



	/**
	 * 执行普通请求
	 */
	_executeNormalRequest(task) {
		return new Promise((resolve, reject) => {
			// 网络状态检测
			// uni.onNetworkStatusChange((res) => {
			// 	if (!res.isConnected) {
			// 		uni.showToast({
			// 			title: '网络连接不可用！',
			// 			icon: 'none'
			// 		});
			// 	}
			// });
			uni.getNetworkType({
				success: (res) => {
					if (res.networkType === 'none') {
						uni.showToast({
							title: '网络连接不可用！',
							icon: 'none'
						});
						return reject(new Error('网络连接不可用'));
					}
				},
				fail: () => {
					uni.showToast({
						title: '无法获取网络状态',
						icon: 'none'
					});
					return reject(new Error('无法获取网络状态'));
				}
			});

			// 用户信息注入
			const param = {
				...task.data
			};
			if (this.APP.getUserInfo()) {
				const userInfo = this.APP.getUserInfo();
				['P_UserID', 'P_UserName', 'P_UserCode', 'P_EmplID'].forEach(key => {
					if (!param.hasOwnProperty(key)) {
						param[key] = userInfo[key.replace('P_', '')];
					}
				});
			}
			
			task.task = uni.request({
				url: task.url,
				data: param,
				method: task.config.method,
				timeout: task.config.timeout,
				header: task.config.header,
				success: (res) => {
					if (res.statusCode >= 200 && res.statusCode < 300) {
						resolve(res.data);
					} else {
						reject(new Error(
							`HTTP ${res.statusCode}: ${res.data?.message || 'Request failed'}`
						));
					}
				},
				fail: reject
			});
		});
	}



	/**
	 * 执行上传请求
	 */
	_executeUpload(task) {
		return new Promise((resolve, reject) => {
			const uploadTask = uni.uploadFile({
				url: task.url,
				filePath: task.data.filePath,
				formData: task.data.formData,
				name: 'file',
				header: task.config.header,
				success: (res) => {
					if (res.statusCode === 200) {
						try {
							resolve(JSON.parse(res.data));
						} catch (e) {
							resolve(res.data);
						}
					} else {
						reject(this._createErrorObject(task, `Upload failed: ${res.statusCode}`,
							res));
					}
				},
				fail: (err) => {
					reject(this._createErrorObject(task, 'Upload failed', err));
				}
			});

			// 监听上传进度
			uploadTask.onProgressUpdate((progressEvent) => {
				const progress = Math.round(progressEvent.progress);

				// 触发进度事件
				this._emit(UniversalRequestQueue.EVENTS.UPLOAD_PROGRESS, {
					requestId: task.id,
					progress,
					totalBytesSent: progressEvent.totalBytesSent,
					totalBytesExpectedToSend: progressEvent.totalBytesExpectedToSend
				});

				// 调用自定义进度回调
				if (typeof task.config.onProgress === 'function') {
					task.config.onProgress(progressEvent);
				}
			});

			task.task = uploadTask;
		});
	}

	/**
	 * 新增的销毁方法（必须存在）
	 */
	destroy() {
		// 取消所有请求
		this.queue.forEach(task => this.cancel(task.id));
		// 清空数据结构
		this.queue = [];
		this.requestMap.clear();
		this.activeRequest = null;
		// 移除所有事件监听
		this.eventListeners.clear();
	}

	// 统一错误对象创建
	_createErrorObject(task, message, errorDetail) {
		return {
			requestId: task.id,
			url: task.url,
			config: task.config,
			message,
			detail: errorDetail,
			timestamp: Date.now(),
			// isNetworkError: !navigator.onLine,
			statusCode: errorDetail?.statusCode || 0
		};
	}

	_handleSuccess(task, result) {
		task.status = 'completed';
		this.requestMap.delete(task.id);
		this.activeRequest = null;

		// 触发成功事件
		this._emit(UniversalRequestQueue.EVENTS.REQUEST_SUCCESS, {
			requestId: task.id,
			result,
			task
		});
		this._emit(UniversalRequestQueue.EVENTS.QUEUE_CHANGE, this._getQueueStatus());

		if (typeof task.success === 'function') {
			task.success(result);
		}
	}

	_handleError(task, error) {
		task.status = 'failed';
		this.requestMap.delete(task.id);
		this.activeRequest = null;

		// 标准化错误对象
		const errorObj = this._createErrorObject(
			task,
			error.message || '请求失败',
			error.detail || error
		);
		// 触发失败事件
		this._emit(UniversalRequestQueue.EVENTS.REQUEST_FAIL, errorObj);
		this._emit(UniversalRequestQueue.EVENTS.QUEUE_CHANGE, this._getQueueStatus());

		if (task.config.toastError) {
			const errorMsg = errorObj.isNetworkError ?
				'网络连接不可用' :
				`请求失败: ${errorObj.message}`;

			uni.showToast({
				title: errorMsg,
				icon: 'none',
				duration: 3000
			});
		}

		if (typeof task.fail === 'function') {
			task.fail(errorObj);
		}

		if (!task.config.ignoreError) {
			this.queue = [];
			this._emit(UniversalRequestQueue.EVENTS.QUEUE_CHANGE, this._getQueueStatus());
		}
	}

	// 获取队列状态（用于事件反馈）
	_getQueueStatus() {
		return {
			activeRequest: this.activeRequest ? this.activeRequest.id : null,
			pendingCount: this.queue.length,
			totalRequests: this.requestMap.size,
			queue: this.queue.map(task => ({
				id: task.id,
				url: task.url,
				status: task.status,
				config: task.config
			}))
		};
	}

	// 在队列操作的关键点添加事件触发
	_enqueue(task) {
		const index = this.queue.findIndex(t => t.config.priority < task.config.priority);
		index === -1 ? this.queue.push(task) : this.queue.splice(index, 0, task);
		this._emit(UniversalRequestQueue.EVENTS.QUEUE_CHANGE, this._getQueueStatus());
	}

	async _processQueue() {
		if (this.activeRequest || this.queue.length === 0) {
			if (!this.activeRequest && this.queue.length === 0) {
				this._emit(UniversalRequestQueue.EVENTS.QUEUE_EMPTY);
			}
			return;
		}

		const nextTask = this.queue.shift();
		this._emit(UniversalRequestQueue.EVENTS.QUEUE_CHANGE, this._getQueueStatus());
		await this._executeRequest(nextTask);
		this._processQueue();
	}

	_delay(ms) {
		return new Promise(resolve => setTimeout(resolve, ms));
	}
}

export default UniversalRequestQueue;